/**
  * Author: Mei
  * Date: 2020-11-29 20:03
  * Description: 智能指针的使用
  *
  */
#include <vector>
#include <queue>
#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <future>
#include <functional>
#include <stdexcept>
#include <iostream>

using namespace std;

class Test {
public:
    void fun() {
        cout << "func()" << endl;
    }

    ~Test() {
        cout << "析构函数" << endl;
    }
};

function<int(int)> wrapper;

int display(int i) {
    cout << i << endl;
    return 1;
}

template<class ...Args>
void invoke(Args &&... args) {
}

template<class ...Args>
void bind_and_forward(Args &&... args) {
    auto binder = std::bind(&invoke<Args&...>, std::forward<Args>(args)...);
    binder();
}

int main() {
    typedef int (*p)(int); //加了typedef表示p是一种类型  指向函数int (*)(int)这种类型
    int (*pp)(int); //不加typedef只表示声明一个函数指针pp  类似于int a 中的a  只是还没赋值
    //pp = display;
    //p a= display;
    //(*a)(1);
    //(*pp)(2);

    /**
     * result_of:
     * template <class Fn, class... ArgTypes>
     * class result_of<Fn(ArgTypes...)>
     * Fn表示可调用对象  要是一个类型  比如上面的int 、 p等类型
     * ArgTypes表示参数列表. 注意是类型(int , string等)
     *
     */
    typedef std::result_of<p(int)>::type B; //也可以这么写
    using return_type = typename std::result_of<p(int)>::type; //要看p(int)的返回值类型为int
    return_type c = 2.12; //return_type为int类型 主要看函数对象的返回值
    B d = 2.22;
    cout << d << endl;

    const int k = 3;
    //make_shared<std::packaged_task<std::decltype(f(args...))()>>(func);
    auto task = std::make_shared<std::packaged_task<return_type(return_type)>>(
            //std::bind(std::forward<p>(display), std::forward<return_type >(444))
            display
    );
    //std::function<decltype(p(1))()> func = std::bind(std::forward<p>(display), std::forward<int>(1111));
    //func();
    //int a = 1;
    //bind_and_forward(a, 2);


    std::future<int> fu1 = task->get_future();
    std::thread t1(std::move(task), 123);
    cout << fu1.get() << endl;

    //typedef decltype(p(122)) a; //声明函数指针类型
    //a aa = display;
    //(*aa)(111);


    //std::function<decltype(f(args...))()> func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
    //auto a = shared_ptr<packaged_task<int(void)>>(
    //
    //);

    //Test *test = new Test;
    //shared_ptr<Test> tt(test);
    //tt->fun();

    return 0;
}